package common.util;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.DatabaseConfiguration;
import org.springframework.context.ApplicationListener;

/**
 * 带缓存的数据库配置
 * 
 * @author Administrator
 *
 */
public class DatabaseCacheConfiguration extends AbstractConfiguration
		implements ApplicationListener<ConfigurationChangeEvent> {

	/** The Map decorated by this configuration. */
	protected Map<String, Object> map = new ConcurrentHashMap<>();
	private DatabaseConfiguration database = null;
	private boolean inited = false;

	public DatabaseCacheConfiguration(DataSource datasource, String table, String nameColumn, String keyColumn,
			String valueColumn, String name) {
		database = new DatabaseConfiguration(datasource, table, nameColumn, keyColumn, valueColumn, name);
		flush();
	}

	public DatabaseCacheConfiguration(DataSource datasource, String table, String keyColumn, String valueColumn) {
		this(datasource, table, null, keyColumn, valueColumn, null);
	}


	protected void flush(){
		Map<String, Object> temp = new HashMap<>();
		Iterator<String> keys = database.getKeys();
		while (keys.hasNext()) {
			String key = (String) keys.next();
			Object value = database.getProperty(key);
			temp.put(key, value);
		}
		Set<String> newkeys = temp.keySet();
		Set<String> oldKeys = map.keySet();
		Collection<String> moreKeys = CollectionUtils.subtract(oldKeys, newkeys);
		synchronized (map) {
			if (!inited) {
				inited = true;
				map.putAll(temp);
				for (String key : moreKeys) {
					map.remove(key);
				}
				inited = false;
			}
		}
	} 


	@Override
	public void onApplicationEvent(ConfigurationChangeEvent event) {
		flush();
	}

	@Override
	public boolean isEmpty() {
		return map.isEmpty();
	}

	@Override
	public boolean containsKey(String key) {
		return map.containsKey(key);
	}

	@Override
	public Object getProperty(String key) {
		return map.get(key);
	}

	@Override
	public Iterator<String> getKeys() {
		return map.keySet().iterator();
	}

	@Override
	protected void addPropertyDirect(String key, Object value) {
		throw new RuntimeException("不允许修改");
	}

}
